package com.koron.ticket.power;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.koron.bean.system.staff.StaffBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.workflow.WorkflowUser;
import com.koron.common.core.business.workflow.bean.po.SysWorkflow;
import com.koron.common.core.business.workflow.service.SysWorkflowService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.StringUtils;
import com.koron.ticket.power.bean.TicketNodeBean;
import com.koron.ticket.power.bean.TicketPowerVo;
import com.koron.ticket.utils.InitData;
import com.koron.ticket.work.enums.TicketType;
import com.koron.ticket.work.workticket.bean.WorkTicket;
import com.koron.ticket.work.workticket.bean.WorkTicketQuery;
import com.koron.ticket.work.workticket.mapper.WorkTicketMapper;
import com.koron.ticket.work.workticket.service.WorkTicketService;
import io.swagger.annotations.Api;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.koron.ticket.work.enums.TicketStatus.*;

@Api(tags = "两票管理-权限")
@RequestMapping("ticket/power")
@RestController
public class TicketPowerService {

    @Autowired
    private SysWorkflowService sysworkflowservice;

    private EamUser getEamuser() {
        return ThreadLocalContext.get();
    }

    private static List<String> commonMsg = CollUtil.newArrayList( "创建单位用户", "开票单位用户");

    @Autowired
    private WorkTicketService workticketservice;

//    @TaskAnnotation("getPower")
//    public TicketPowerVo getPower(SessionFactory factory, String id) {
//
//        // true权限隐藏、 false权限显示
//        TicketPowerVo ticketPowerVo = new TicketPowerVo();
//
//
//        WorkTicket ticketBean = factory.getMapper(WorkTicketMapper.class).getSingle(new WorkTicketQuery(id));
//        String ticketUnit = ticketBean.getUnit();//获取工作票开票单位
//        String createByUnit = ticketBean.getDeptId();//获取创建人单位
//
//        List<WorkflowUser> ticketUnitUserlist = getPowerUser(ticketUnit);
//        List<WorkflowUser> createByUnitUserlist = getPowerUser(createByUnit);
//        List<String> ticketUnitAcclist = ticketUnitUserlist.stream().map(WorkflowUser::getCode).collect(Collectors.toList()); //开票单位所有账号
//        List<String> createByUnitAcclist = createByUnitUserlist.stream().map(WorkflowUser::getCode).collect(Collectors.toList());//创建人单位所有账号
//
//        boolean unitBoo = ticketUnitAcclist.contains(getEamuser().getAccount());
//        boolean createByUnitBoo = createByUnitAcclist.contains(getEamuser().getAccount());
//
//        List<TicketNodeBean> gasandmechanics = InitData.initGasAndMechanicsNode();
//        setGasAndMechanicsPower(unitBoo, createByUnitBoo, gasandmechanics);
//        ticketPowerVo.setGasAndMechanics(gasandmechanics);// 电气第一第二种、机械工作票集合
//
//        List<TicketNodeBean> third = InitData.initThirdicsNode();
//        setThirdPower(unitBoo, createByUnitBoo, third);
//        ticketPowerVo.setThird(third);// 第三种工作票集合
//
//        List<TicketNodeBean> secondeLevel = InitData.initSecondeLevelNode();
//        setSecondLevel(unitBoo, createByUnitBoo, secondeLevel);
//        ticketPowerVo.setSecondLevel(secondeLevel);// 动火第二种工作票集合
//
//        List<TicketNodeBean> powerLin = InitData.initPowerLinNode();
//        setSecondLevel(unitBoo, createByUnitBoo, powerLin);
//        ticketPowerVo.setPowerLin(powerLin);// 线路第一第二种工作票集合
//
//        return ticketPowerVo;
//    }

    @TaskAnnotation("getPowerNew")
    public TicketNodeBean getPowerNew(SessionFactory factory, String id, String type, Integer status) {

        // true权限隐藏、 false权限显示
        TicketPowerVo ticketPowerVo = new TicketPowerVo();

        WorkTicket ticketBean = factory.getMapper(WorkTicketMapper.class).getSingle(new WorkTicketQuery(id));
        String ticketUnit = ticketBean.getUnit();//获取工作票开票单位
        String createByUnit = Opt.ofNullable(ticketBean.getCreateDept()).orElse(ticketBean.getDeptId());//获取创建人单位

        List<WorkflowUser> ticketUnitUserlist = getPowerUser(ticketUnit);
        List<WorkflowUser> createByUnitUserlist = getPowerUser(createByUnit);
        List<String> ticketUnitAcclist = ticketUnitUserlist.stream().map(WorkflowUser::getCode).collect(Collectors.toList()); //开票单位所有账号
        List<String> createByUnitAcclist = createByUnitUserlist.stream().map(WorkflowUser::getCode).collect(Collectors.toList());//创建人单位所有账号

        SysWorkflow sysWorkflow = sysworkflowservice.queryRunByDataId(id);//但前处理人id
        String curnodeuserid = Opt.ofNullable(sysWorkflow).map(SysWorkflow::getCurNodeUserId).orElse("");
        List<String> curnodeuserList = StrUtil.split(curnodeuserid, ",");//但前流程处理人


        boolean unitBoo = ticketUnitAcclist.contains(getEamuser().getAccount());
        boolean createByUnitBoo = createByUnitAcclist.contains(getEamuser().getAccount());
        boolean curnodeuserBoo = curnodeuserList.contains(getEamuser().getAccount());

        List<TicketNodeBean> nodelist = new ArrayList<>();

        if (StrUtil.equalsAny(type, TicketType.ElectricalFirst.getType(), TicketType.ElectricalSecond.getType(), TicketType.MechanicalTicket.getType(), TicketType.ZsjBidSectionFirst.getType())) {
            nodelist = InitData.initGasAndMechanicsNode(unitBoo, createByUnitBoo, curnodeuserBoo);
            setGasAndMechanicsPower(unitBoo, createByUnitBoo, nodelist);// 电气第一第二种、机械工作票集合
        }

        if (StrUtil.equalsAny(type, TicketType.ThirdTicket.getType())) {
            nodelist = InitData.initThirdicsNode(unitBoo, createByUnitBoo, curnodeuserBoo);
            setThirdPower(unitBoo, createByUnitBoo, nodelist);//第三种工作票集合
        }

        if (StrUtil.equalsAny(type, TicketType.SecondLevelHotWork.getType())) {
            nodelist = InitData.initSecondeLevelNode(unitBoo, createByUnitBoo, curnodeuserBoo);
            setSecondLevel(unitBoo, createByUnitBoo, nodelist);//动火第二种工作票集合
        }

        if (StrUtil.equalsAny(type, TicketType.PowerLineFirst.getType(), TicketType.PowerLineSecond.getType())) {
            nodelist = InitData.initPowerLinNode(unitBoo, createByUnitBoo, curnodeuserBoo);
            setPowerLin(unitBoo, createByUnitBoo, nodelist);//线路第一第二种工作票集合
        }

        if (StrUtil.equalsAny(type, TicketType.ZsjBidSectionSecond.getType())){
            nodelist = InitData.initZsjBidSectionSecondNode(unitBoo, createByUnitBoo, curnodeuserBoo);
            setZsjBidSectionSecond(unitBoo, createByUnitBoo, nodelist);//珠三角第二种工作票集合
        }

        Optional<TicketNodeBean> first = nodelist.stream().filter(n -> n.getStatus() == status).findFirst();
        if (first.isPresent()) {
            return first.get();
        } else {
            Assert.isFalse(true, "相应工作票的节点不存在");
        }

        return new TicketNodeBean();
    }

    private void setZsjBidSectionSecond(boolean unitBoo, boolean createByUnitBoo, List<TicketNodeBean> ticketNodeBeans) {
        ticketNodeBeans.stream().forEach(n -> {
            // 填写
            if (n.getStatus().equals(WRITE.getStatus())) {
                if(unitBoo || createByUnitBoo){
                    n.getDet().stream().forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", String.join(",", commonMsg))));
            }
            // 待许可
            if (n.getStatus().equals(PERMIT.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));//创建单位用户除了申请操作票其他都有权限
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("operationTicket"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 工作待终结
            if (n.getStatus().equals(WORK_END.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("change")).forEach(p -> p.setIsPower(false));
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("change"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 已归档
            if (n.getStatus().equals(ARCHIVED.getStatus())) {
                n.getDet().stream().filter(p -> StrUtil.equalsAny(p.getCode(),"save","commit","delete")).forEach(p -> {
                    p.setIsPower(true);
                    p.setMsg("工作票已归档不允许修改");
                });
                backePowerUsre(commonMsg, n);
            }
        });
    }

    public List<String> getAccount(String ticketUnit) {
        //获取开票单位的人的账号
        StaffBean staffBean = new StaffBean();
        staffBean.setOrgId(ticketUnit);
        List<WorkflowUser> resultlist = workticketservice.getWorkflowThisUnitUsers(staffBean);
        if (StringUtils.isNotEmpty(resultlist)) {
            return resultlist.stream().map(WorkflowUser::getCode).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    public List<WorkflowUser> getPowerUser(String ticketUnit) {
        //获取开票单位的人的账号
        StaffBean staffBean = new StaffBean();
        staffBean.setOrgId(ticketUnit);
        List<WorkflowUser> resultlist = workticketservice.getWorkflowThisUnitUsers(staffBean);
        if (StringUtils.isNotEmpty(resultlist)) {
            return resultlist;
        }
        return new ArrayList<>();
    }


    /**
     * 获取审批人
     *
     * @param id 工作票id
     * @return
     */
    @TaskAnnotation("getTicketApproverThisUnitNoPost")
    public List<WorkflowUser> getTicketApproverThisUnitNoPost(SessionFactory factory, String id) {
        String unit = factory.getMapper(WorkTicketMapper.class).getSingle(new WorkTicketQuery(id)).getUnit();//获取开票单位id
        StaffBean staffBean = new StaffBean();
        staffBean.setOrgId(unit);
        List<WorkflowUser> resultlist = workticketservice.getWorkflowThisUnitUsers(staffBean);
        if (StringUtils.isNotEmpty(resultlist)) {
            return resultlist;
        }
        return new ArrayList();
    }

    /**
     * 配置线路一二种工作票权限
     *
     * @param unitBoo         登录用户是否在 开票单位下
     * @param createByUnitBoo 登录用户是否在 创建人单位下
     * @param ticketNodeBeans
     */
    private void setPowerLin(Boolean unitBoo, Boolean createByUnitBoo, List<TicketNodeBean> ticketNodeBeans) {
        ticketNodeBeans.stream().forEach(n -> {
            // 填写
            if (n.getStatus().equals(WRITE.getStatus())) {
                if (createByUnitBoo || unitBoo) {
                    n.getDet().stream().forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", String.join(",", commonMsg))));
            }
            // 待签发
            if (n.getStatus().equals(SIGN.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 待会签
            if (n.getStatus().equals(COUNTERSIGN.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 待接受
            if (n.getStatus().equals(ACCEPT.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 待许可
            if (n.getStatus().equals(PERMIT.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 工作待终结
            if (n.getStatus().equals(WORK_END.getStatus())) {
                if (createByUnitBoo || unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("change")).forEach(p -> p.setIsPower(false));
                }
                n.getDet().stream().filter(p -> p.getCode().equals("change") && p.getIsPower()).forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "创建单位用户,开票单位用户")));
                backePowerUsre(commonMsg, n);
            }
            // 工作票待终结
            if (n.getStatus().equals(TICKET_END.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 已归档
            if (n.getStatus().equals(ARCHIVED.getStatus())) {
                n.getDet().stream().filter(p -> StrUtil.equalsAny(p.getCode(),"save","commit","delete")).forEach(p -> {
                    p.setIsPower(true);
                    p.setMsg("工作票已归档不允许修改");
                });
                backePowerUsre(commonMsg, n);
            }
        });
    }


    /**
     * 返回有权限用户
     *
     * @param msglist
     * @param n
     */
    private void backePowerUsre(List<String> msglist, TicketNodeBean n) {
        String msg = StrUtil.format("仅以下用户能操作：{}", String.join(",", msglist));
        String saveMsg = StrUtil.format("仅以下用户能操作：{}", "流程审批人");
        n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.isBlank(p.getMsg())).forEach(p -> p.setMsg(msg));
        n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit")).forEach(p -> p.setMsg(saveMsg));
    }

    /**
     * 配置动火第二种工作票权限
     *
     * @param unitBoo         登录用户是否在 开票单位下
     * @param createByUnitBoo 登录用户是否在 创建人单位下
     * @param secondeLevel
     */
    private void setSecondLevel(Boolean unitBoo, Boolean createByUnitBoo, List<TicketNodeBean> secondeLevel) {
        secondeLevel.stream().forEach(n -> {
            // 填写
            if (n.getStatus().equals(WRITE.getStatus())) {
                if(unitBoo || createByUnitBoo){
                    n.getDet().stream().forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", String.join(",", commonMsg))));
            }
            // 待签发
            if (n.getStatus().equals(SIGN.getStatus())) {
                backePowerUsre(commonMsg, n);

            }
            // 待会签
            if (n.getStatus().equals(COUNTERSIGN.getStatus())) {
                backePowerUsre(commonMsg, n);

            }
            // 待接受
            if (n.getStatus().equals(ACCEPT.getStatus())) {
                backePowerUsre(commonMsg, n);

            }
            // 待许可
            if (n.getStatus().equals(PERMIT.getStatus())) {
                backePowerUsre(commonMsg, n);

            }
            // 工作待终结
            if (n.getStatus().equals(WORK_END.getStatus())) {
                backePowerUsre(commonMsg, n);

            }
            // 已归档
            if (n.getStatus().equals(ARCHIVED.getStatus())) {
                n.getDet().stream().filter(p -> StrUtil.equalsAny(p.getCode(),"save","commit","delete")).forEach(p -> {
                    p.setIsPower(true);
                    p.setMsg("工作票已归档不允许修改");
                });
                backePowerUsre(commonMsg, n);
            }
        });
    }

    /**
     * 配置第三种工作票权限
     *
     * @param unitBoo         登录用户是否在 开票单位下
     * @param createByUnitBoo 登录用户是否在 创建人单位下
     * @param third
     */
    private void setThirdPower(Boolean unitBoo, Boolean createByUnitBoo, List<TicketNodeBean> third) {
        third.stream().forEach(n -> {
            // 填写
            if (n.getStatus().equals(WRITE.getStatus())) {
                if(unitBoo || createByUnitBoo){
                    n.getDet().stream().forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", String.join(",", commonMsg))));
            }
            // 待许可
            if (n.getStatus().equals(PERMIT.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("operationTicket"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 工作票待终结
            if (n.getStatus().equals(TICKET_END.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("operationTicket"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 已归档
            if (n.getStatus().equals(ARCHIVED.getStatus())) {
                n.getDet().stream().filter(p -> StrUtil.equalsAny(p.getCode(),"save","commit","delete")).forEach(p -> {
                    p.setIsPower(true);
                    p.setMsg("工作票已归档不允许修改");
                });
                backePowerUsre(commonMsg, n);
            }
        });
    }

    /**
     * 配置第一二种工作票、机械工作票权限
     *
     * @param unitBoo         登录用户是否在 开票单位下
     * @param createByUnitBoo 登录用户是否在 创建人单位下
     * @param ticketNodeBeans
     */
    private void setGasAndMechanicsPower(Boolean unitBoo, Boolean createByUnitBoo, List<TicketNodeBean> ticketNodeBeans) {
        ticketNodeBeans.stream().forEach(n -> {
            // 填写
            if (n.getStatus().equals(WRITE.getStatus())) {
                if(unitBoo || createByUnitBoo){
                    n.getDet().stream().forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && StrUtil.equalsAny(p.getCode(),"save", "commit"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", String.join(",", commonMsg))));
            }
            // 待签发
            if (n.getStatus().equals(SIGN.getStatus())) {
                //通用权限
                backePowerUsre(commonMsg, n);
            }
            // 待会签
            if (n.getStatus().equals(COUNTERSIGN.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 待接受
            if (n.getStatus().equals(ACCEPT.getStatus())) {
                backePowerUsre(commonMsg, n);
            }
            // 待许可
            if (n.getStatus().equals(PERMIT.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));//创建单位用户除了申请操作票其他都有权限
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("operationTicket"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 工作待终结
            if (n.getStatus().equals(WORK_END.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("change")).forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("change"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 工作票待终结
            if (n.getStatus().equals(TICKET_END.getStatus())) {
                if (unitBoo) {
                    n.getDet().stream().filter(p -> p.getCode().equals("operationTicket")).forEach(p -> p.setIsPower(false));
                }
                backePowerUsre(commonMsg, n);
                n.getDet().stream().filter(p -> p.getIsPower() && p.getCode().equals("operationTicket"))
                        .forEach(p -> p.setMsg(StrUtil.format("仅以下用户能操作：{}", "开票单位用户")));
            }
            // 已归档
            if (n.getStatus().equals(ARCHIVED.getStatus())) {
                n.getDet().stream().filter(p -> StrUtil.equalsAny(p.getCode(),"save","commit","delete")).forEach(p -> {
                    p.setIsPower(true);
                    p.setMsg("工作票已归档不允许修改");
                });
                backePowerUsre(commonMsg, n);
            }
        });
    }

    /**
     * 所有人都有
     * 更多-操作记录
     * 更多-查看流程
     *
     * @param n
     */
    private void commonPower(TicketNodeBean n) {
        n.getDet().stream().forEach(p -> {
            if (StrUtil.equalsAny(p.getCode(), "preview", "record", "process")) {
                p.setIsPower(false);
            }
        });
    }

}
